//===============================================================================
// Microsoft patterns & practices
// Guidance Explorer Offline Client
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.Windows.Forms;
using GuidanceExplorer.Model;
using GuidanceExplorer.Model.Conditions;

namespace GuidanceExplorer.Controls
{
    /// <summary>
    /// The node for a single library.
    /// </summary>
    [MenuItemAttribute(500, "context\\New Item", GuidanceExplorer.Commands.NewGuidanceItem, typeof(ModelItemMenuItemIsEditableCondition), Keys.None)]
    [MenuItemAttribute(505, "context\\New Item Template", GuidanceExplorer.Commands.NewGuidanceItem, typeof(ModelItemMenuItemIsEditableCondition), typeof(NewItemMenuItemProvider), Keys.None)]
    [MenuItemAttribute(510, "context\\-", null, typeof(OrGenericMenuItemCondition<ModelItemMenuItemIsEditableCondition, MenuItemUnderSolutionNodeCondition>), Keys.None)]
    [MenuItemAttribute(520, "context\\Import Item...", GuidanceExplorer.Commands.ImportGuidanceItemToView, typeof(AndGenericMenuItemCondition<NotGenericMenuItemCondition<MenuItemUnderSolutionNodeCondition>, ModelItemMenuItemIsEditableCondition>), Keys.None)]
    //[MenuItemAttribute(521, "context\\Save View as...", GuidanceExplorer.Commands.SaveViewAs, Keys.None)]
    [MenuItemAttribute(530, "context\\Export as Library...", GuidanceExplorer.Commands.ExportViewAsLibrary, typeof(NotGenericMenuItemCondition<MenuItemUnderSolutionNodeCondition>), Keys.None)]
    [MenuItemAttribute(535, "context\\Export View...", GuidanceExplorer.Commands.ExportSolutionModelItem, typeof(MenuItemUnderSolutionNodeCondition), Keys.None)]
    [MenuItemAttribute(540, "context\\-", null, typeof(OrGenericMenuItemCondition<ModelItemMenuItemIsEditableCondition, MenuItemUnderSolutionNodeCondition>), Keys.None)]
    [MenuItemAttribute(550, "context\\Rename View", GuidanceExplorer.Commands.RenameView, typeof(ModelItemMenuItemIsEditableCondition), Keys.None)]
    [MenuItemAttribute(560, "context\\Delete View", GuidanceExplorer.Commands.DeleteView, typeof(ModelItemMenuItemIsEditableCondition), Keys.None)]
    //[MenuItemAttribute(570, "context\\-", null, typeof(WebSubscribedLibraryCondition), Keys.None)]
    //[MenuItemAttribute(575, "context\\Synchronize Library", Commands.Synchronize, typeof(WebSubscribedLibraryCondition), Keys.None)]
#if ONLINEENABLED
    [MenuItemAttribute(580, "context\\Remove (experimental)", Commands.RemoveView, typeof(WebSubscribedLibraryCondition), Keys.None)]
    [MenuItemAttribute(590, "context\\Publish (experimental)...", GuidanceExplorer.Commands.PublishView, Keys.None)]
    //[MenuItemAttribute(595, "context\\SSE Synchronize (experimental)", Commands.SSESynchronize, Keys.None)]
#endif
    public class ViewNode : ModelNode<GuidanceExplorer.Model.View>
    {
        /// <summary>
        /// Factory.
        /// </summary>
        /// <returns></returns>
        public static ViewNode New()
        {
            return new ViewNode();
        }

        /// <summary>
        /// Default constructor.
        /// </summary>
        private ViewNode() : base("<a view>", 0, 0) { }

        /// <summary>
        /// Whether the node can be dropped.
        /// </summary>
        public override bool CanDrop(IModelItem modelNode)
        {
		
			GuidanceExplorer.Model.View view = null;
			Library thisLibrary = ModelInstance.GetContainerLibrary();
            GuidanceItem guidanceItem = modelNode as GuidanceItem;
            GuidanceItemCollection guidanceItemCollection = modelNode as GuidanceItemCollection;
				
			ViewNode viewNode = modelNode as ViewNode;
			GuidanceItemNode guidanceItemNode = modelNode as GuidanceItemNode;
			ChecklistNode checkListNode = modelNode as ChecklistNode;
			FolderNode folderNode = modelNode as FolderNode;
			SearchViewNode svn = modelNode as SearchViewNode;

			MenuItemUnderSolutionNodeCondition isUnderSolutioNode = new MenuItemUnderSolutionNodeCondition();

            if (guidanceItem != null || guidanceItemCollection != null || guidanceItemNode != null)
            {
				// TODO: Review this.
				return thisLibrary == null || thisLibrary.ReadProtection == ReadProtection.ReadWrite;
            }
			else if (guidanceItemNode != null)
			{
				ViewNode vNode = guidanceItemNode.Parent as ViewNode;
				ChecklistNode checklistNode = guidanceItemNode.Parent as ChecklistNode;
				SearchViewNode searchViewNode = guidanceItemNode.Parent as SearchViewNode;
                GuidanceTypeNode guidanceTypeNode = guidanceItemNode.Parent as GuidanceTypeNode;

				if (vNode != null)
				{
					if (isUnderSolutioNode.ShowMenuItem(null,vNode) && IsUnderMyViews(this)) return false;

					if (isUnderSolutioNode.ShowMenuItem(null, vNode) && IsUnderLibrary(this)) return false;

					return true;
				}
				if (checklistNode != null)
				{
					if (isUnderSolutioNode.ShowMenuItem(null, checklistNode) && IsUnderMyViews(this)) return false;

					if (isUnderSolutioNode.ShowMenuItem(null, checklistNode) && IsUnderLibrary(this)) return false;

					return true;

				}
				if (searchViewNode != null)
				{
					if (isUnderSolutioNode.ShowMenuItem(null, searchViewNode) && IsUnderMyViews(this)) return false;

					if (isUnderSolutioNode.ShowMenuItem(null, searchViewNode) && IsUnderLibrary(this)) return false;

					return true;
					
				}
                if (guidanceTypeNode != null)
                {
                    return true;
                }
            }
			else if (viewNode != null)
			{
				if (isUnderSolutioNode.ShowMenuItem(null, viewNode)) return false;
				if (IsUnderMyViews(this) || IsUnderLibrary(this) ) return false;

				view = viewNode.ModelInstance;
			}
			if (view != null)
			{
				/*
				 * Test for views:
				 *  Only views of the same library can be drop in the library.
				 *  Views can't be droped in its parent folder.
				 */
				Library otherLibrary = view.GetContainerLibrary();

				//Root views cant be dragged
				if (view.RootView)
				{
					return false;
				}

				//Can't drag to its parent.
				if (Object.ReferenceEquals(view.ParentFolder, ModelInstance))
				{
					return false;
				}
				return true;
			}
			else if (checkListNode != null)
			{
				if (isUnderSolutioNode.ShowMenuItem(null, checkListNode)) return false;

				if (isUnderSolutioNode.ShowMenuItem(null, checkListNode) && IsUnderMyViews(this)) return false;

				if (isUnderSolutioNode.ShowMenuItem(null, checkListNode) && IsUnderLibrary(this)) return false;

				return true;
			}
			else if (folderNode != null)
			{
				if (isUnderSolutioNode.ShowMenuItem(null, folderNode) && IsUnderMyViews(this)) return false;

				if (isUnderSolutioNode.ShowMenuItem(null, folderNode) && IsUnderLibrary(this)) return false;

				if (IsUnderLibrary(this) || IsUnderMyViews(this)) return false;

				if (isUnderSolutioNode.ShowMenuItem(null, this) && isUnderSolutioNode.ShowMenuItem(null, folderNode)) return false;

				return true;
			}
			else if (svn != null)
			{
				if (isUnderSolutioNode.ShowMenuItem(null, svn) && IsUnderMyViews(this)) return false;

				if (isUnderSolutioNode.ShowMenuItem(null, svn) && IsUnderLibrary(this)) return false;

				if (IsUnderLibrary(this)) return false;

				return true;
			}
			return false;
        }

		public bool IsUnderLibrary(ViewNode viewNode)
		{
			if (viewNode.ModelInstance.ParentFolder != null)
			{
				Folder folder = viewNode.ModelInstance.ParentFolder;
				while (folder != null)
				{
					if ((folder.Container != null) && (folder.Container.GetType() == typeof(Library)))
					{
						return true;
					}
					folder = folder.ParentFolder;
				}
				return false;

			}
			else if (viewNode.ModelInstance.Container.GetType() == typeof(Library))
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		public bool IsUnderMyViews(ViewNode viewNode)
		{
			if (viewNode.ModelInstance.ParentFolder != null)
			{
				Folder folder = viewNode.ModelInstance.ParentFolder;
				while (folder != null)
				{
					if ((folder.Container != null) && (folder.Container.GetType() == typeof(UserViews)))
					{
						return true;
					}
					folder = folder.ParentFolder;
				}
				return false;

			}
			else if (viewNode.ModelInstance.Container.GetType() == typeof(UserViews))
			{
				return true;
			}
			else
			{
				return false;
			}

		}

        /// <summary>
        /// Whether the node is editable.
        /// </summary>
        public override bool IsEditable
        {
            get
            {
                Library library = ModelInstance.GetContainerLibrary();
                if (library != null)
                {
                    return (library.ReadProtection == ReadProtection.ReadWrite);
                }
                return true;
            }
        }

		/// <summary>
		/// Clone a ViewNode
		/// </summary>
		public ViewNode Clone(GuidanceExplorer.Model.View newModelInstance)
		{
			ViewNode cloneNode = new ViewNode();

			cloneNode.Text = Text;
			if (newModelInstance == null)
			{
				cloneNode.ModelInstance = (GuidanceExplorer.Model.View)ModelInstance.Clone();
			}
			else
			{
				cloneNode.ModelInstance = newModelInstance;
			}
			cloneNode.SelectedItem = SelectedItem;

			if ( Nodes.Count > 0 )
			{
				foreach (TreeNode tempNode in Nodes)
				{
					GuidanceItemNode tempGuiItemNode = tempNode as GuidanceItemNode;
					TreeNode copyNode = null;

					if (tempGuiItemNode != null)
					{
						GuidanceItemFileReference ItemFileReference = tempGuiItemNode.ModelInstance.Clone();
						copyNode = (TreeNode)tempGuiItemNode.Clone(ItemFileReference);
					}

					cloneNode.Nodes.Add(copyNode);
				}
			}

			return cloneNode;
		}

    }
}

